package gldemo;

import org.lwjgl.opengl.*;
import org.lwjgl.input.*;
import org.lwjgl.util.glu.*;
import glapp.*;

/**
 * Render a scene with a skydome and a ground plane.  Use arrow keys to navigate the scene.
 * <P>
 * @see GLCamera.java
 * @see GLCam.java
 * <P>
 * napier at potatoland dot org
 */
public class GLApp_DemoSkydomeSimple extends GLApp {
    // Handles for textures
    int sphereTextureHandle = 0;
    int sphereTextureHandleD = 0;
    int groundTextureHandle = 0;
    int houseTextureHandle = 0;
    // display list for skydome
    int skydomeDL = 0;
    // Light position: if last value is 0, then this describes light direction.  If 1, then light position.
    float lightPosition[]= { -2f, 2f, 2f, 0f };
    // a camera and a cam to move around scene
    GLCamera camera1 = new GLCamera();
    GLCam cam = new GLCam(camera1);
    // SPACE key toggles dusk/daylight
    boolean dusk = false;
    
    /**
     * Initialize application and run main loop.
     */
    public static void main(String args[]) {
    	GLApp_DemoSkydomeSimple demo = new GLApp_DemoSkydomeSimple();
        demo.VSyncEnabled = true;
        demo.fullScreen = false;
        demo.run();  // will call init(), render(), mouse functions
    }

    /**
     * Initialize the scene.  Called by GLApp.run()
     */
    public void setup()
    {
        // setup and enable perspective
        setPerspective();

        // Create a light (diffuse light, ambient light, position)
        setLight( GL11.GL_LIGHT1,
        		new float[] { .51f, .51f, .51f, 1f },
        		new float[] { .5f, .5f, .53f, 1f },
        		new float[] { .1f, .1f, .1f, 1f },
        		lightPosition );

        // bright light overall
        setAmbientLight(new float[] {1f, 1f, 1f, 1});
        
        // medium bright material
        setMaterial(new float[] {.8f, .8f, .8f, 1}, .5f);
        
        // enable lighting and texture rendering
        GL11.glEnable(GL11.GL_LIGHTING);
        GL11.glEnable(GL11.GL_TEXTURE_2D);

        // Enable alpha transparency (so text will have transparent background)
        GL11.glEnable(GL11.GL_BLEND);
        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

        // Create textures
        sphereTextureHandle = makeTexture("images/dayfair_skydome_1.jpg");
        sphereTextureHandleD = makeTexture("images/dayfair_skydome_1_dusk.jpg");
        groundTextureHandle = makeTexture("images/grass_1_512.jpg",true,true);
        houseTextureHandle = makeTexture("images/house_Stirling_House_t.png");

        // set camera 1 position
        camera1.setCamera(
        		0,25,130,           // position of camera 
        		-.1f, 0f, -1,      // direction camera is pointing NOT TARGET POSITION (differerent from glulookat!)
        		0,1,0);             // UP direction of camera

        // a little haze
        setFog(new float[] {.5f,.5f,.5f,1f}, .001f);
        
        // make the skydome display list
        makeSkyDome();
    }
    
    public void makeSkyDome() {
    	Sphere s = new Sphere();       // an LWJGL class for drawing sphere
    	s.setOrientation(GLU.GLU_INSIDE);  // normals point inwards
    	s.setTextureFlag(true);           // generate texture coords
    	skydomeDL = beginDisplayList();
    	{
    		GL11.glDisable(GL11.GL_LIGHTING);
    		GL11.glDisable(GL11.GL_DEPTH_TEST);
    		GL11.glColor4f(.62f,.62f,.626f,1);
    		GL11.glPushMatrix();
    		{
    			GL11.glTranslatef(camera1.Position.x,camera1.Position.y,camera1.Position.z);
    			GL11.glRotatef(90f, 1,0,0);     // rotate the sphere to align the axis vertically
    			GL11.glScalef(200,200,200);
    			s.draw(1, 48, 48);              // run GL commands to draw sphere
    		}
    		GL11.glPopMatrix();
    		GL11.glEnable(GL11.GL_LIGHTING);
    		GL11.glEnable(GL11.GL_DEPTH_TEST);
    	}
    	endDisplayList();
    }
    
    public void renderDome() {
		GL11.glBindTexture(GL11.GL_TEXTURE_2D, dusk? sphereTextureHandleD : sphereTextureHandle);
    	callDisplayList(skydomeDL);
    }

    public void renderHouse() {
        // draw the house on a plane
        GL11.glPushMatrix();
        {
            GL11.glTranslatef(0f, 70f, 0f);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, houseTextureHandle);
            renderPlane(150,150,10,10);
        }
        GL11.glPopMatrix();
    }

    public void renderGround() {
        // draw the ground plane
        GL11.glPushMatrix();
        {
        	GL11.glRotatef(-90,1,0,0);
            GL11.glBindTexture(GL11.GL_TEXTURE_2D, groundTextureHandle);
            renderPlane(1000,1000,100,100,40,40);
        }
        GL11.glPopMatrix();
    }

    /**
     * set the field of view and view depth.
     */
    public static void setPerspective()
    {
        // select projection matrix (controls perspective)
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        // fovy, aspect ratio, zNear, zFar
        GLU.gluPerspective(50f,         // zoom in or out of view
                           aspectRatio, // shape of viewport rectangle
                           .1f,         // Min Z: how far from eye position does view start
                           5000f);       // max Z: how far from eye position does view extend
        // return to modelview matrix
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
    }

    /**
     * Render one frame.  Called by GLApp.run().
     */
    public void draw() {
        // user keystrokes adjust camera position    	
        cam.handleNavKeys((float)GLApp.getSecondsPerFrame());

        // clear depth buffer and color
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        // select model view for subsequent transforms
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glLoadIdentity();

        // do gluLookAt() with camera position, direction, orientation
        cam.render();

        // draw the sky
        renderDome();
        
        // draw the ground plane
        GL11.glPushMatrix();
        {
            GL11.glTranslatef(0f, -3f, 0f); // down a bit
            renderGround();
        }
        GL11.glPopMatrix();

        // draw house
        GL11.glPushMatrix();
        {
            GL11.glTranslatef(0f, 0f, -50f);
            renderHouse();
        }
        GL11.glPopMatrix();
        
        // Place the light.  Light will stay in sync with the rest of the scene
        setLightPosition(GL11.GL_LIGHT1, lightPosition);

		// render some text using texture-mapped font
        print( 30, viewportH- 80, "Left-Right arrows rotate camera", 1);
        print( 30, viewportH-100, "Up-Down arrows move camera forward and back", 1);
        print( 30, viewportH-120, "SPACE toggles dusk/daylight", 1);
        print( 30, viewportH-140, "A W S D keys tilt and pan the camer", 1);
    }

    public void keyDown(int keycode) {
    	if (keycode == Keyboard.KEY_SPACE) {
    		dusk = !dusk;
    		if (dusk) {
    			setAmbientLight(new float[] {.1f, .1f, .1f, 1});
    		}
    		else {
    	        setAmbientLight(new float[] {1f, 1f, 1f, 1});
    		}
    	}
    }
}